/*
Copyright 2010 Richard Carter (Ricky28269)

Game of Life for Google Apps Script version 2 (2010/11/08)

Game of Life for Google Apps Script is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

Game of Life for Google Apps Script is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with Game of Life for Google Apps Script. If not, see http://www.gnu.org/licenses/.
*/

function onOpen() {
  var subMenus = [{name:"Set Size", functionName:"setSize"},{name:"Start",functionName:"start"},{name:"Stop",functionName:"stop"},{name:"Tick", functionName:"tick"}];
  SpreadsheetApp.getActiveSpreadsheet().addMenu("Game of Life", subMenus);
}

function setSize() {
  var cols = Browser.inputBox("Size", "How many columns?", Browser.Buttons.OK);
  cols = parseInt(cols);
  var rows = Browser.inputBox("Size", "How many rows?", Browser.Buttons.OK);
  rows = parseInt(rows);
  
  if(cols <= 0) cols = 10;
  if(rows <= 0) rows = 10;
  
  var sheet = SpreadsheetApp.getActiveSheet();
  
  if(cols > sheet.getMaxColumns()) {
    sheet.insertColumns(1, cols - sheet.getMaxColumns());
  }
  if(cols < sheet.getMaxColumns()) {
    sheet.deleteColumns(1, sheet.getMaxColumns() - cols);
  }
  if(rows+1 > sheet.getMaxRows()) {
    sheet.insertRows(1, (rows+1) - sheet.getMaxRows());
  }
  if(rows+1 < sheet.getMaxRows()) {
    sheet.deleteRows(1, sheet.getMaxRows() - (rows + 1));
  }
  
  for(var col = 1; col <= cols; col++) {
    sheet.setColumnWidth(col, 20);
  }
  
  for(var row = 1; row <= rows+1; row++) {
    sheet.setRowHeight(row, 20);
  }
  
  sheet.clear();
  
  sheet.getRange(1,1,sheet.getMaxRows(),sheet.getMaxColumns()).breakApart();
  sheet.getRange(1,1,1,sheet.getMaxColumns()-2).mergeAcross().setBackgroundColor("#e0e0e0").setValue("Conway's Game of Life*");
  sheet.getRange(1,sheet.getMaxColumns()-1,1,1).setBackgroundColor("#000000");
  sheet.getRange(1,sheet.getMaxColumns()-0,1,1).setBackgroundColor("#ffffff");

  SpreadsheetApp.flush();
}

function start() {
  var sheet = SpreadsheetApp.getActiveSheet();
  sheet.getRange(1,1,1,1).setValue("Conway's Game of Life");
}

function stop() {
  var sheet = SpreadsheetApp.getActiveSheet();
  sheet.getRange(1,1,1,1).setValue("Conway's Game of Life*");
}

function autoTick() {
  var sheet = SpreadsheetApp.getActiveSheet();
  for(var sec=1; sec<60; sec++) {
    var before = new Date();
    
    if(sheet.getRange(1,1,1,1).getValue() == "Conway's Game of Life") {
      tick();
    }
    
    var after = new Date();
    var duration = after.getTime() - before.getTime();
    
    if(duration < 1000)
      Utilities.sleep(1000-(after.getTime()-before.getTime()));
  }
}

function timedTick() { // for debugging purposes
  var before = new Date();
  tick();
  var after = new Date();
  var duration = after.getTime() - before.getTime();
  Logger.log("Duration: "+duration);
}

function tick() {

  var sheet = SpreadsheetApp.getActiveSheet();
  var cols = sheet.getMaxColumns();
  var rows = sheet.getMaxRows();
  
  var currentGeneration = sheet.getRange(1, 1, rows, cols).getBackgroundColors();
  var nextGeneration = new Array();
  nextGeneration[0] = currentGeneration[0];
  
  for(var row = 2; row <= rows; row++) {
    nextGeneration[row-1] = new Array();
    for(var col = 1; col <= cols; col++) {
      
      // count neighbors
      var neighbors = 0;
      for(var colOff = -1; colOff <= 1; colOff++) {
        for(var rowOff = -1; rowOff <= 1; rowOff++) {
          if(colOff == 0 && rowOff == 0) {
            continue;
          }
          
          var ncol = (col+colOff);
          if(ncol == 0) ncol = cols;
          if(ncol == cols+1) ncol = 1;
          var nrow = (row+rowOff);
          if(nrow == 1) nrow = rows;
          if(nrow == rows+1) nrow = 2;
          
          if(currentGeneration[nrow-1][ncol-1] == "#000000") {
            neighbors++;
          }
        }
      }
      
      if(currentGeneration[row-1][col-1] == "#000000") {
        // live
        nextGeneration[row-1][col-1] = !(neighbors<2 || neighbors>3);
      } else {
        // dead
        nextGeneration[row-1][col-1] = (neighbors == 3);
      }
    }
  } // end of outer for
  
  
  for(var row = 2; row <= rows; row++) {
    for(var col = 1; col <= cols; col++) {
      if(nextGeneration[row-1][col-1]) {
        if(currentGeneration[row-1][col-1] != "#000000") {
          nextGeneration[row-1][col-1] = "#000000";
        }
      } else {
        if(currentGeneration[row-1][col-1] != "#ffffff") {
          nextGeneration[row-1][col-1] = "#ffffff";
        }
      }
    }
  }
  
  sheet.getRange(1, 1, rows, cols).setBackgroundColors(nextGeneration);
  
  SpreadsheetApp.flush();              
}
